<?php

namespace App\Http\Controllers;

use App\Models\Dorm;
use App\Models\DormMeter;
use App\Models\DormMeterRecord;
use App\Models\MeterType;
use App\Models\Period;
use Prettus\Validator\Contracts\ValidatorInterface;
use Prettus\Validator\Exceptions\ValidatorException;
use App\Http\Requests\DormMeterAdjustCreateRequest;
use App\Http\Requests\DormMeterAdjustUpdateRequest;
use App\Repositories\DormMeterAdjustRepository;
use App\Validators\DormMeterAdjustValidator;

/**
 * Class DormMeterAdjustsController.
 *
 * @package namespace App\Http\Controllers;
 */
class DormMeterAdjustsController extends Controller
{
    /**
     * @var DormMeterAdjustRepository
     */
    protected $repository;

    /**
     * @var DormMeterAdjustValidator
     */
    protected $validator;

    /**
     * DormMeterAdjustsController constructor.
     *
     * @param DormMeterAdjustRepository $repository
     * @param DormMeterAdjustValidator $validator
     */
    public function __construct(DormMeterAdjustRepository $repository, DormMeterAdjustValidator $validator)
    {
        $this->repository = $repository;
        $this->validator  = $validator;
    }

    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $this->repository->pushCriteria(app('Prettus\Repository\Criteria\RequestCriteria'));
        $dormMeterAdjusts = $this->repository
            ->with(['company', 'dorm:id,code', 'meterType:id,name', 'dormMeterOld:id,nfc_id', 'dormMeterNew:id,nfc_id'])
            ->paginate(\request()->get('limit', 20));

        if (request()->wantsJson()) {
            return response()->json([
                'data' => $dormMeterAdjusts,
            ]);
        }

        return view('dormMeterAdjusts.index', compact('dormMeterAdjusts'));
    }

    public function create()
    {
        $dorm_id = request()->get('dorm_id');
        $dorm = Dorm::find($dorm_id);
        $is_replace = request()->get('action') === 'replace';
        $meter_id = \request()->get('meter_type');
        $meter_type = MeterType::find($meter_id);
        if ($is_replace) {

            $old_meter = DormMeter::query()->where([['dorm_id', $dorm_id], ['meter_type_id', $meter_id], ['active', 1]])->first();
            $ms = preg_match('/.+(\d+)/', $old_meter->nfc_id, $reg);
            if ($ms) {
                $i = $reg[1] + 1;
            } else {
                $i = 1;
            }

            return view('dormMeterAdjusts.create', compact('dorm', 'meter_type', 'is_replace', 'old_meter', 'i'));
        } else {
            return view('dormMeterAdjusts.create', compact('dorm', 'meter_type', 'is_replace'));
        }
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  DormMeterAdjustCreateRequest $request
     *
     * @return \Illuminate\Http\Response
     *
     * @throws \Prettus\Validator\Exceptions\ValidatorException
     */
    public function store(DormMeterAdjustCreateRequest $request)
    {
        try {
            //            $this->validator->with($request->all())->passesOrFail(ValidatorInterface::RULE_CREATE);
            $dorm = Dorm::find($request->get('dorm_id'));
            $meterTypeId = $request->get('meter_type');
            $adjustDate = $request->get('adjust_date');
            $oldMeter = null;
            \DB::beginTransaction();

            if ($request->get('is_replace')) {
                $period = Period::query()->where('start_date', '<=', $adjustDate)->where('end_date', '>=', $adjustDate)->first();
                if ($period) {
                    $oldMeter = Dormmeter::query()->where('dorm_id', $dorm->id)->where('meter_type_id', $meterTypeId)->where('active', 1)->first();
                    $consume = $request->get('old_meter_reading') - $oldMeter->last_reading;
                    if ($consume >= 0) {
                        //更换水表或更换电表
                        $oldMeter->active = 0;
                        $oldMeter->expire_date = $adjustDate;
                        $oldMeter->last_reading = $request->get('old_meter_reading');
                        $oldMeter->save();

                        $record = new DormMeterRecord();
                        $record->dorm_id = $dorm->id;
                        $record->period_id = $period->id;
                        $record->dorm_meter_id = $oldMeter->id;
                        $record->meter_type_id = $meterTypeId;
                        $record->prev_meter_reading = $request->get('old_meter_prev_reading');
                        $record->meter_reading = $request->get('old_meter_reading');
                        $record->meter_reading_date = $adjustDate;
                        $record->day_span = floor((strtotime($adjustDate) - strtotime($oldMeter->last_reading_date)) / 86400);
                        $record->consume = $consume;
                        $record->user_id = \Auth::user()->id;
                        $record->save();
                    } else {
                        throw new \Exception('旧表读数不能小于上一次读数');
                    }
                } else {
                    throw new \Exception('换表日期必须在已将创建的周期范围内');
                }
            }

            $tid = $request->get('nfc_id');

            if (DormMeter::where('nfc_id', $tid)->count()) {
                \DB::rollBack();
                $msg = "新表TID必须唯一，$tid 已经存在";
                if ($request->wantsJson()) {
                    return response()->json(['error'   => true, 'message' => $msg]);
                }
                return redirect()->back()->withErrors($msg)->withInput();
            }
            $newMeter = DormMeter::create([
                'dorm_id' => $dorm->id,
                'meter_type_id' => $meterTypeId,
                'nfc_id' => $tid,
                'last_reading' => $request->get('last_reading'),
                'last_reading_date' => $adjustDate,
                'install_date' => $adjustDate
            ]);
            $dormMeterAdjust = $this->repository->create([
                'dorm_id' => $dorm->id,
                'meter_type_id' => $meterTypeId,
                'dorm_meter_id_old' => optional($oldMeter)->id,
                'dorm_meter_id_new' => $newMeter->id,
                'adjust_date' => $adjustDate
            ]);
            \DB::commit();
            $response = [
                'message' => 'DormMeterAdjust created.',
                'data'    => $dormMeterAdjust->toArray(),
            ];
            if ($request->wantsJson()) {
                return response()->json($response);
            }

            return redirect()->back()->with('message', $response['message']);
        } catch (\Exception $e) {
            \DB::rollBack();
            if ($request->wantsJson()) {
                return response()->json([
                    'error'   => true,
                    'message' => $e->getMessage()
                ]);
            }
            return redirect()->back()->withErrors($e->getMessage())->withInput();
        }
    }

    /**
     * Display the specified resource.
     *
     * @param  int $id
     *
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        $dormMeterAdjust = $this->repository->find($id);

        if (request()->wantsJson()) {

            return response()->json([
                'data' => $dormMeterAdjust,
            ]);
        }

        return view('dormMeterAdjusts.show', compact('dormMeterAdjust'));
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int $id
     *
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        $dormMeterAdjust = $this->repository->find($id);

        return view('dormMeterAdjusts.edit', compact('dormMeterAdjust'));
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  DormMeterAdjustUpdateRequest $request
     * @param  string            $id
     *
     * @return Response
     *
     * @throws \Prettus\Validator\Exceptions\ValidatorException
     */
    public function update(DormMeterAdjustUpdateRequest $request, $id)
    {
        try {

            $this->validator->with($request->all())->passesOrFail(ValidatorInterface::RULE_UPDATE);

            $dormMeterAdjust = $this->repository->update($request->all(), $id);

            $response = [
                'message' => 'DormMeterAdjust updated.',
                'data'    => $dormMeterAdjust->toArray(),
            ];

            if ($request->wantsJson()) {

                return response()->json($response);
            }

            return redirect()->back()->with('message', $response['message']);
        } catch (ValidatorException $e) {

            if ($request->wantsJson()) {

                return response()->json([
                    'error'   => true,
                    'message' => $e->getMessageBag()
                ]);
            }

            return redirect()->back()->withErrors($e->getMessageBag())->withInput();
        }
    }


    /**
     * Remove the specified resource from storage.
     *
     * @param  int $id
     *
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        $deleted = $this->repository->delete($id);

        if (request()->wantsJson()) {

            return response()->json([
                'message' => 'DormMeterAdjust deleted.',
                'deleted' => $deleted,
            ]);
        }

        return redirect()->back()->with('message', 'DormMeterAdjust deleted.');
    }
}
